import numpy as np
#from matplotlib.pyplot import plot, savefig, title, legend, ylim, cla, xlabel, ylabel, annotate
from time import clock

#@profile
def Method_Iterative(A, b, Precision):

	Iteration_Matrix, Constant_Matrix, Initial_Vector = Generate_Matrix_for_Iterate(A, b)
	Error = abs(Precision) + 1
	X = Initial_Vector
	while Error > abs(Precision):
		X_next = Iteration_Matrix*X + Constant_Matrix
		X_next_next = Iteration_Matrix*X_next + Constant_Matrix
		# Error_1 = abs(np.mean(X_next - X))
		# Error_2 = abs(np.mean(X_next_next - 2*X_next + X))
		Error = abs(np.mean(X_next_next - X_next))
		X = X_next_next
		print(Error)
	return X, Error

def Generate_Matrix_for_Iterate(A, b):
	'''
	A = M - N 
	N = M - A
	x = M^{-1}*N*x + M^{-1}*b
	x = Iteration_Matrix*x + Constant_Matrix
	'''
	Dimention = A.shape[0]
	M = A.item(0,0)*np.matrix(np.eye(Dimention,Dimention))
	N = M - A
	M_inv = 1/A.item(0,0)#*np.matrix(np.eye(Dimention,Dimention))
	Iteration_Matrix = M_inv*N#np.dot(M_inv,N)#
	Constant_Matrix = M_inv*b
	Initial_Vector = 0*np.matrix(np.ones([Dimention,1]))
	#print(Iteration_Matrix)
	return Iteration_Matrix, Constant_Matrix, Initial_Vector




# A = np.matrix("-4,1,0,1,0,0,0,0,0;1,-4,1,0,1,0,0,0,0;0,1,-4,0,0,1,0,0,0;1,0,0,-4,1,0,1,0,0;0,1,0,1,-4,1,0,1,0;0,0,1,0,1,-4,0,0,1;0,0,0,1,0,0,-4,1,0;0,0,0,0,1,0,1,-4,1;0,0,0,0,0,1,0,1,-4")
# b=np.matrix("5;6;7;8;9;7;8;9;2")

def Generate_Matrix_A_b():
	#Diagonal Matrix Kernal
	D = np.matrix("-4,1,0;1,-4,1;0,1,-4")
	#The Matrix near by Diagonal Matrix Kernal
	H = np.matrix("1,0,0;0,1,0;0,0,1")
	#The Zero Matrix
	Z = np.matrix("0,0,0;0,0,0;0,0,0")

	#Kernel_String = "H,D,H,Z,Z"
	Kernel_String = "H,D,H,Z,Z,Z,Z,Z,Z,Z,Z"
	Some_Z = ",Z,Z,Z,Z,Z"*100
	Kernel_String = Kernel_String + Some_Z
	Matrix_String = Kernel_String[2:]
	#First -1 because Kernel_String is one more than real, Second -1 becasue there is a value out of loop
	for i in range(int((len(Kernel_String)-1)/2)-1):
		Matrix_String = Matrix_String+";"+"Z,"*i+Kernel_String[0:len(Kernel_String)-(i+1)*2]
	A = np.bmat(Matrix_String)

	Vector_b_String = str(int(np.random.random()*10))
	#First -1 because Kernel_String is one more than real, Second -1 becasue there is a value out of loop
	for i in range(int((len(Kernel_String)-1)/2*D.shape[0])-1):
		Vector_b_String = Vector_b_String+";"+str(int(np.random.random()*10))
	b = np.matrix(Vector_b_String)
	# with open("matrix_file", 'w') as mf:
	# 	A.tofile(mf)
	# 	b.tofile(mf)
	np.savetxt("matrix_file", A)
	return A, b

#np.set_printoptions(threshold='nan')
A, b = Generate_Matrix_A_b()
# start_time = clock()
# print("Direct Method:\n", A.I*b, A.shape)
# end_time = clock()
# print("\nUse time:", end_time - start_time)

print("Begin Calcule!\n")
start_time = clock()
print("\nIterative Method:\n", Method_Iterative(A, b, 1e-5), A.shape)
end_time = clock()
print("\nUse time:", end_time - start_time)


# #Diagonal Matrix Kernal
# D = np.matrix("-4,1,0;1,-4,0;0,1,-4")
# #The Matrix near by Diagonal Matrix Kernal
# H = np.matrix("1,0,0;0,1,0;0,0,1")
# #The Zero Matrix
# Z = np.matrix("0,0,0;0,0,0;0,0,0")

# Kernel_String="H,D,H,Z,Z,Z,Z"
# Matrix_String=Kernel_String[2:]
# for i in range(int((len(Kernel_String)-1)/2)-1):
# 	Matrix_String = Matrix_String+";"+"Z,"*i+Kernel_String[0:len(Kernel_String)-(i+1)*2]
# A = np.bmat(Matrix_String)